﻿using System.Device.Location;
using System;
using System.Linq;
using System.Net;
using System.Xml.Linq;
using Microsoft.Phone.Net.NetworkInformation;

namespace TaxiPlease.PhoneHelpers
{
	public class LocationService
	{
		private GeoCoordinateWatcher watcher;
		private WebClient client;

		public event EventHandler<AddressEventArgs> AddressChanged;
		public event EventHandler<LocationEventArgs> LocationChanged;

		public void Start()
		{
			this.watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);			
			this.watcher.StatusChanged += watcher_StatusChanged;
			this.watcher.Start();
		}

		public void Stop()
		{
			if (watcher != null)
			{
				watcher.StatusChanged -= watcher_StatusChanged;
				watcher.Stop();
				watcher.Dispose();
			}
			watcher = null;
			client = null;
		}
		private void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
		{
			if (e.Status == GeoPositionStatus.Ready)
			{				
				this.OnLocationChanged(watcher.Position.Location);
				ReverseLocation(watcher.Position.Location);
			}

			if (e.Status == GeoPositionStatus.Disabled)
			{
				this.OnAddressChanged(null);
			}
		}

		private void ReverseLocation(GeoCoordinate location)
		{
			if (NetworkInterface.GetIsNetworkAvailable())
			{
				string uri = string.Format("http://maps.googleapis.com/maps/api/geocode/xml?latlng={0},{1}&sensor=true", location.Latitude, location.Longitude);
				client = new WebClient();
				client.DownloadStringCompleted += Client_DownloadStringCompleted;
				client.DownloadStringAsync(new Uri(uri));
			}
			else
			{
				this.OnAddressChanged(null);
			}
		}

		private void Client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
		{
			XDocument doc = XDocument.Parse(e.Result);
			var text = doc.Descendants("formatted_address").FirstOrDefault();
			if (text != null)
			{
				this.OnAddressChanged(text.Value.ToString());
			}

			if (client != null)
			{
				client.DownloadStringCompleted -= Client_DownloadStringCompleted;
			}
			client = null;
		}

		private void OnAddressChanged(string address)
		{
			if (AddressChanged != null)
			{
				AddressChanged(this, new AddressEventArgs
				{
					Address = address
				});
			}
		}

		private void OnLocationChanged(GeoCoordinate location)
		{
			if (LocationChanged != null)
			{
				LocationChanged(this, new LocationEventArgs
				{
					Location = location
				});
			}
		}
	}

	public class AddressEventArgs : EventArgs
	{
		public string Address
		{
			get;
			set;
		}
	}

	public class LocationEventArgs : EventArgs
	{
		public GeoCoordinate Location
		{
			get;
			set;
		}
	}
}
